package com.hd.trans.camerax

import android.graphics.Bitmap
import android.graphics.Point
import android.util.Log
import me.pqpo.smartcropperlib.SmartCropper
import kotlin.collections.ArrayList
import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sqrt

/**
 * @author       qianjujun
 * @email        qianjujun@163.com
 * @createTime   2022/8/25
 * @describe     寻找合适的裁剪区域
 */
abstract class FindCrop {

    companion object{
        const val TAG = "FindCrop"
    }

    abstract fun testCrop(image: Bitmap): ScanResult

     fun isFullCrop(points:Array<Point>,w:Int,h:Int):Boolean{
        if(points.size!=4){
            return false
        }
        if(points[0]!= Point(0,0)){
            return false
        }
        if(points[1]!= Point(w, 0)){
            return false
        }
        if(points[2]!=Point(w, h)){
            return false
        }
        if(points[3]!=Point(0, h)){
            return false
        }
        return true

    }
}





fun distance(p0: Point, p1: Point): Float {
    return sqrt((p0.x - p1.x).toDouble().pow(2.0) + (p0.y - p1.y).toDouble().pow(2.0)).toFloat()
}

/**
 * 全局分析
 */
class MyFindCrop(private val mConfigData: FindCropConfig) : FindCrop() {

    private data class CropData(val d1:Float,val d2:Float,val d3:Float)

    private val mScanResult by lazy {
        ScanResult()
    }

    companion object {
        /**
         * 每5帧计算一次
         */
        const val PER_COUNT_FRAME_NUM = 5

        /**
         * 缓存的最大数据个数
         */
        const val MAX_CACHE_DATA = 8

        /**
         * 最大误差值
         */
        const val MAX_FIX_SCALE = 0.1f

        /**
         * 相似值个数为7
         */
        const val CORRECT_NUM = 3
    }







    private val mCacheDataList = ArrayList<CropData>()


    override fun testCrop(image: Bitmap): ScanResult {

        val points = SmartCropper.scan(image)

        val isCropAll = isFullCrop(points, image.width, image.height)


        if (isCropAll) {
            return mScanResult.apply {
                this.code = ScanResult.CODE_SEARCH_ING
                this.data = null
            }
        }

        val d1 = distance(points[0], points[3])
        val d2 = distance(points[0], points[1])
        val d3 = distance(points[0], points[2])


        if (mConfigData.isFilter) {
            //过滤掉凹边
            if (d3 < d1 || d3 < d2) {
                return mScanResult.apply {
                    this.code = ScanResult.CODE_SEARCH_ING
                    this.data = null
                }
            }
        }


        //旋转后的图片
        val imageW = image.width
        val imageH = image.height


        if (mConfigData.isFilter) {
            //过滤掉太小的裁边
            if (d1 < imageH * 0.3f || d2 < imageW * 0.3f) {
                return mScanResult.apply {
                    this.code = ScanResult.CODE_SEARCH_ING
                    this.data = null
                }
            }
        }


        val temp = mCacheDataList.filter {
            val scale1 = it.d1 / d1
            val scale2 = it.d2 / d2
            val scale3 = it.d3 / d3

            Log.d(
                TAG,
                "testCrop() called scale1 = ${scale1}  scale2 = ${scale2}  scale3 = ${scale3}"
            )
            abs(scale1 - scale2) < mConfigData.maxFixScale && abs(scale1 - scale3) < mConfigData.maxFixScale && abs(
                scale2 - scale3
            ) < mConfigData.maxFixScale
        }

        if (temp.size >= mConfigData.maxCache) {
            mCacheDataList.clear()
            return mScanResult.apply {
                this.code = ScanResult.CODE_SUCCESS
                this.data = points
                this.scanImageWidth = imageW
                this.scanImageHeight = imageH
            }
        }


        mCacheDataList.add(CropData(d1, d2, d3))

        if (mCacheDataList.size > mConfigData.maxCache) {
            mCacheDataList.removeAt(0)
        }

        return mScanResult.apply {
            this.code = ScanResult.CODE_FIX_ING
            this.data = points
            this.scanImageWidth = imageW
            this.scanImageHeight = imageH
        }
    }

}



data class FindCropConfig(var preCountFrameNum:Int = MyFindCrop.PER_COUNT_FRAME_NUM
                          , var maxCache :Int = MyFindCrop.MAX_CACHE_DATA
                          , var maxFixScale :Float = MyFindCrop.MAX_FIX_SCALE
                          , var correctNum:Int = MyFindCrop.CORRECT_NUM, var isFilter:Boolean = true)